/* 
 * File:   Cliente.h
 * Author: max
 *
 * Created on October 20, 2012, 9:05 AM
 */

#ifndef CLIENTE_H
#define	CLIENTE_H

#include <string>
#include <cstdlib>
#include <iostream>
#include <ostream>
#include <vector>
#include "client_SocketAsincronico.h"
#include "client_IEnviante.h"
#include "client_IMensajero.h"
#include "client_IObservadorSocketManejadorEvento.h"
#include "client_IRepositorioPollerManejadorEvento.h"
#include "client_ObservadorSocket.h"
#include "client_IRespuestaServidorManejador.h"
#include "client_FileServiceProxy.h"
#include "client_EcoServiceProxy.h"
#include "client_RepositorioPoller.h"
#include "client_Operacion.h"
#include "client_OperacionSincronizacionRepositorio.h"
#include "common_Excepcion.h"
#include "common_Repositorio.h"
#include "common_ClientConfFileManager.h"
#include "common_Mutex.h"
#include "common_FileUtils.h"

#define OK "OK"
#define SINCRONIZACION_REPOSITORIO_TOKEN 100000
#define NOMBRE_ARCHIVO_REPOSITORIO_SERIALIZADO "repositorio.xml" 

using namespace std;
using namespace TP;
using namespace TP::Servicios;
using namespace TP::Operaciones;
using namespace TP::Comunicacion;
using namespace TP::Comunicacion::Eventos;
using namespace TP::Archivos;

namespace TP { namespace Comunicacion { 

    class Cliente : public IObservadorSocketManejadorEvento
    {
    
    public:
    
        Cliente(ClientConfFileManager* pConfigurationManager, std::ostream& pLog);

        virtual ~Cliente();

        void Iniciar() throw (Excepcion&);
        
        void Finalizar() throw (Excepcion&);
        
        virtual void PersistirRepositorio ();  
        
        virtual string GetDirectorioAPolear();

        /* notificacionErrorConexion:
         *      Maneja los mensajes de error de conexion por parte del socket.
         */
        void notificarErrorConexion (IEnviante* pEnviante, const string& pMensaje);
        
        /* notificarMensajeEntrante:
         *      Maneja la notificacion de un mensaje entrante a traves del socket.
         */
        void notificarMensajeEntranteServidor (IEnviante* pEnviante, const string& pMensaje);
    
    private:

        bool Autenticar();
        
        string GetCredencial ();
        
        vector<string> hidratarMensaje(const string& pMensaje) throw (Excepcion &);

        void IniciarRepositorio();
        
        void IniciarRepositorioPoller() throw (Excepcion&) ;
        
        void ManejarNotificacionArchivoNuevo(vector<string> &pMensaje);
        
        void ManejarNotificacionArchivoBorrado(vector<string> &pMensaje);
        
        IRespuestaServidorManejador* AddRespuestaServidorManejador (IRespuestaServidorManejador* pManejador);
        
        IRespuestaServidorManejador* RespuestaServidorManejadorPrimero ();
        
        IRespuestaServidorManejador* RespuestaServidorManejadorSiguiente (IRespuestaServidorManejador* pActual);

        std::ostream& _log;
        SocketAsincronico* _socket;
        ObservadorSocket* _observadorSocket;
        vector<IRespuestaServidorManejador*> _respuestaServidorManejadores;
        Mutex _respuestaServidorManejadoresMutex;
        
        RepositorioPoller* _repositorioPoller;
        Repositorio* _repositorio;
        ClientConfFileManager* _config;
        FileServiceProxy* _fileService;
        EcoServiceProxy* _ecoService;
        FileUtils _fileUtils;
    };
}}

#endif	/* CLIENTE_H */

